package com.nbsaas.boot;

import javax.tools.*;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;

public class DynamicCodeExecutor2 {
    public static Object executeCode(String code) throws Exception {
        // 使用Java Compiler API编译代码并加载类
        compileAndLoadClass("DynamicCode", code);

        // 加载并执行编译后的类
        Class<?> loadedClass = Class.forName("DynamicCode");
        Method method = loadedClass.getMethod("execute");
        return method.invoke(null);
    }

    // 使用Java Compiler API编译代码并加载类
    private static void compileAndLoadClass(String className, String code) throws Exception {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            throw new RuntimeException("Java编译器未找到，请确保JDK安装正确");
        }

        // 创建文件管理器
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        // 创建一个输出流，用于接收编译过程中的输出信息
        StringWriter outputWriter = new StringWriter();

        // 创建编译任务
        JavaFileObject sourceFile = new JavaSourceFromString(className, code);
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile);
        JavaCompiler.CompilationTask task = compiler.getTask(outputWriter, fileManager, null, null, null, compilationUnits);

        // 执行编译任务
        boolean success = task.call();
        fileManager.close();

        if (!success) {
            throw new RuntimeException("代码编译失败: " + outputWriter.toString());
        }
    }

    // 使用Java Compiler API编译代码并加载类
    private static Class<?> compileAndLoadClass1(String className, String code) throws Exception {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        if (compiler == null) {
            throw new RuntimeException("Java编译器未找到，请确保JDK安装正确");
        }

        // 创建文件管理器
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
        // 创建一个输出流，用于接收编译过程中的输出信息
        StringWriter outputWriter = new StringWriter();

        // 创建编译任务
        JavaFileObject sourceFile = new JavaSourceFromString(className, code);
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(sourceFile);
        JavaCompiler.CompilationTask task = compiler.getTask(outputWriter, fileManager, null, null, null, compilationUnits);

        // 执行编译任务
        boolean success = task.call();
        fileManager.close();

        if (!success) {
            throw new RuntimeException("代码编译失败: " + outputWriter.toString());
        }
        // 返回加载后的类
        MyClassLoader classLoader = new MyClassLoader();
        return classLoader.loadClass(className);
        // 返回加载后的类
    }

    // 自定义Java源文件对象
    static class JavaSourceFromString extends SimpleJavaFileObject {
        final String code;

        JavaSourceFromString(String className, String code) {
            super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return this.code;
        }
    }

    // 自定义ClassLoader用于加载动态编译后的类
    static class MyClassLoader extends ClassLoader {
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            try {
                return findClass(name);
            } catch (ClassNotFoundException e) {
                return super.loadClass(name);
            }
        }
    }

    public static void main(String[] args) {
        String code = "public class DynamicCode { public static void execute() { System.out.println(\"Dynamic code executed\"); } }";
        try {
            // 编译代码并加载类
            Class<?> loadedClass = compileAndLoadClass1("DynamicCode", code);
            // 执行加载后的类
            Method method = loadedClass.getMethod("execute");
            method.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
